package com.ykefu.assign.netty.netty;

import com.ykefu.assign.constant.MimeType;
import com.ykefu.assign.netty.netty.http.HttpController;
import com.ykefu.assign.netty.netty.http.ResponseWriteUtil;
import com.ykefu.assign.netty.netty.websocket.ChannelManager;
import io.netty.buffer.ByteBuf;
import io.netty.channel.*;
import io.netty.handler.codec.http.*;
import io.netty.handler.ssl.SslHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE;
import static io.netty.handler.codec.http.HttpMethod.GET;
import static io.netty.handler.codec.http.HttpResponseStatus.*;

/**
 * @author likai
 * @date 2020/4/17 9:01
 * @email likai@7moor..com
 * @desc
 */
public class NettyHttpProtocolHandler extends SimpleChannelInboundHandler<FullHttpRequest> {

    private static final Logger LOGGER = LoggerFactory.getLogger(NettyHttpProtocolHandler.class);

    private final String websocketPath;

    public NettyHttpProtocolHandler(String websocketPath) {
        this.websocketPath = websocketPath;
    }



    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception {
        // Handle a bad request.
        if (!req.decoderResult().isSuccess()) {
            ResponseWriteUtil.sendHttpResponse(ctx, req, new DefaultFullHttpResponse(req.protocolVersion(), BAD_REQUEST,
                    ctx.alloc().buffer(0)));
            return;
        }
        //send msg to channel
        if("/api".equals(req.uri())){
            HttpController.handler(ctx,req);
        }
        // Allow only GET methods.
        if (!GET.equals(req.method())) {
            ResponseWriteUtil.sendHttpResponse(ctx, req, new DefaultFullHttpResponse(req.protocolVersion(), FORBIDDEN,
                    ctx.alloc().buffer(0)));
            return;
        }
        // Send the index page
        if ("/".equals(req.uri()) || "/index.html".equals(req.uri())) {
            String webSocketLocation = getWebSocketLocation(ctx.pipeline(), req, websocketPath);
            ByteBuf content = NettyConnectPage.getContent(webSocketLocation);
            FullHttpResponse res = new DefaultFullHttpResponse(req.protocolVersion(), OK, content);
            res.headers().set(CONTENT_TYPE, MimeType.text_html);
            HttpUtil.setContentLength(res, content.readableBytes());
            ResponseWriteUtil.sendHttpResponse(ctx, req, res);
        } else {
            ResponseWriteUtil.sendHttpResponse(ctx, req, new DefaultFullHttpResponse(req.protocolVersion(), NOT_FOUND,
                    ctx.alloc().buffer(0)));
        }
    }


    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        ChannelManager.getInstance().delChannel(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        cause.printStackTrace();
        ctx.close();
    }



    private static String getWebSocketLocation(ChannelPipeline cp, HttpRequest req, String path) {
        String protocol = "ws";
        if (cp.get(SslHandler.class) != null) {
            // SSL in use so use Secure WebSockets
            protocol = "wss";
        }
        return protocol + "://" + req.headers().get(HttpHeaderNames.HOST) + path;
    }
}
